﻿// <copyright file="FeatureLayerUtility.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>FeatureLayerUtility class</summary>

namespace BESASM.EMGAATS.UI.ArcMap
{
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using BESASM.EMGAATS.Arc;
  using BESASM.EMGAATS.BusinessClasses;
  using ESRI.ArcGIS.Carto;
  using ESRI.ArcGIS.Display;
  using ESRI.ArcGIS.esriSystem;
  using ESRI.ArcGIS.Geodatabase;
  using ESRI.ArcGIS.Geometry;

  /// <summary>
  /// A utility class for working with feature layers
  /// </summary>
  public static class FeatureLayerUtility
  {
    /// <summary>
    /// Retrieves the entity layer for the given type from the given map.
    /// </summary>
    /// <param name="map">The map to search for the feature layer.</param>
    /// <param name="entityType">The entity type.</param>
    /// <returns>The entity layer for the given type.</returns>
    public static IFeatureLayer GetEntityLayer(IMap map, EntityType entityType)
    {
      // Get feature layers
      UIDClass uid = new UIDClass();
      uid.Value = "{40A9E885-5533-11d0-98BE-00805F7CED21}";
      IEnumLayer enumLayers = map.get_Layers(uid, true);
      IFeatureLayer entityLayer = enumLayers.Next() as IFeatureLayer;
      while (entityLayer != null)
      {
        if (entityLayer.FeatureClass != null)
        {
          if (entityType == EmgaatsExtension.Instance.NetworkManager.GetObjectClassEntityType(entityLayer.FeatureClass))
          {
            return entityLayer;
          }
        }

        entityLayer = enumLayers.Next() as IFeatureLayer;
      }

      return null;
    }

    /// <summary>
    /// Finds the first visible entity at the given location (based on layer order)
    /// </summary>
    /// <param name="map">The map on which to find the entity.</param>
    /// <param name="x">The screen x-coordinate (pixel) for the location.</param>
    /// <param name="y">The screen y-coordinate (pixel) for the location.</param>
    /// <param name="pixelTolerance">The pixel tolerance to allow for nearby entities to be found.</param>
    /// <param name="entityLayer">The layer the entity feature was found in.</param>
    /// <returns>The first visible entity at the given location, or null if none exists there.</returns>
    public static IFeature FindEntityAtLocation(IMap map, int x, int y, int pixelTolerance, out IFeatureLayer entityLayer)
    {
      // Get target area by expanding point and transforming to map coordinates
      tagRECT r;

      r.left = x - pixelTolerance;
      r.top = y - pixelTolerance;
      r.right = x + pixelTolerance;
      r.bottom = y + pixelTolerance;

      int transformOptions = (int)(esriDisplayTransformationEnum.esriTransformPosition | esriDisplayTransformationEnum.esriTransformToMap);
      IEnvelope envelope = new EnvelopeClass();
      IActiveView activeView = map as IActiveView;
      IDisplayTransformation transform = activeView.ScreenDisplay.DisplayTransformation;
      transform.TransformRect(envelope, ref r, transformOptions);

      envelope.SpatialReference = map.SpatialReference;

      // Get visible feature layers
      UIDClass uid = new UIDClass();
      uid.Value = "{40A9E885-5533-11d0-98BE-00805F7CED21}";
      IEnumLayer enumLayers = map.get_Layers(uid, true);
      entityLayer = enumLayers.Next() as IFeatureLayer;
      while (entityLayer != null)
      {
        if (entityLayer.Visible && entityLayer.FeatureClass != null)
        {
          EntityType entityType = EmgaatsExtension.Instance.NetworkManager.GetObjectClassEntityType(entityLayer.FeatureClass);
          if (entityType != EntityType.Unknown)
          {
            ISpatialFilter filter = new SpatialFilterClass();
            filter.Geometry = envelope;
            filter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

            IFeatureCursor cursor = entityLayer.Search(filter, false);
            try
            {
              IFeature feature = cursor.NextFeature();
              if (feature != null)
              {
                return feature;
              }
              else
              {
                ComUtility.ReleaseComObject(feature);
              }
            }
            finally
            {
              ComUtility.ReleaseComObject(cursor);
            }
          }
        }

        entityLayer = enumLayers.Next() as IFeatureLayer;
      }

      return null;
    }
  }
}
